(function (root, factory) {
  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
  root.t2c = factory();
}(this, function () { 'use strict';

const valueTypeOptions = {
  STRING: "''",
  ARRAY: "[]",
  CLASS: "Class",
  CLASSARRAY: "Class []",
  OBJ: "{}",
  BOOL: 'Boolean',
  KEYCLASSOBJ: "{ key: Class }"
}

function prop(key, type) {
  let modelCode = '';
  switch (type) {
    case valueTypeOptions.STRING:
      modelCode += `${key} = ${valueTypeOptions.STRING};`;
      break;
    case valueTypeOptions.ARRAY:
      modelCode += `${key} = ${valueTypeOptions.ARRAY};`;
      break;
    case valueTypeOptions.OBJ:
      modelCode += `${key} = ${valueTypeOptions.OBJ};`;
      break;
    case valueTypeOptions.KEYCLASSOBJ:
      modelCode += `${key} = ${valueTypeOptions.OBJ};`;
      break;
    case valueTypeOptions.CLASSARRAY:
      modelCode += `${key} = ${valueTypeOptions.ARRAY};`;
      break;
    case valueTypeOptions.BOOL:
      modelCode += `${key} = false;`;
      break;
    case valueTypeOptions.CLASS:
      modelCode += `${key} = new ${valueTypeOptions.CLASS}();`;
      break
  }
  // console.log('prop:', modelCode)
  return modelCode;
}

function construct(key, type) {
  let modelCode = '';
  switch (type) {
    case valueTypeOptions.STRING:
      modelCode += `this.${key} = data.${key} || ${type};`;
      break;
    case valueTypeOptions.ARRAY:
      modelCode += `this.${key} = _.map(data.${key}, Class.parse) || [];`;
      break;
    case valueTypeOptions.OBJ:
      modelCode += `this.${key} = _.isEmpty(data.${key}) ? null : data.${key};`;
      break;
    case valueTypeOptions.KEYCLASSOBJ:
      modelCode += `this.${key} = {};\n`
                 + `_.each(data.${key}, (clazz, key) => {\n`
                 + `  this.${key}[key] = Class.parse(clazz);\n`
                 + `})`;
      break;
    case valueTypeOptions.CLASSARRAY:
      modelCode += `this.${key} = _.map(data.${key}, Class.parse) || [];`;
      break;
    case valueTypeOptions.BOOL:
      modelCode += `this.${key} = data.${key} !== undefined ? data.${key} : undefined;`;
      break;
    case valueTypeOptions.CLASS:
      modelCode += `this.${key} = Class.parse(data.${key});`;
      break
  }
  // console.log('construct:', modelCode)
  return modelCode;
}

function toServer(key, type) {
  let modelCode = '';
  switch (type) {
    case valueTypeOptions.STRING:
      modelCode += `this.${key} && (ret.${key} = this.${key});`;
      break;
    case valueTypeOptions.ARRAY:
      modelCode += `!_.isEmpty(this.${key}) && (ret.${key} = this.${key});`;
      break;
    case valueTypeOptions.OBJ:
      modelCode += `this.${key} && (ret.${key} = this.${key});`;
      break;
    case valueTypeOptions.KEYCLASSOBJ:
      modelCode += `this.${key} && (ret.${key} = this.${key});`;
      break;
    case valueTypeOptions.CLASSARRAY:
      modelCode += `!_.isEmpty(this.${key}) && (ret.${key} = _.map(this.${key}, item => item.toServer()));`;
      break;
    case valueTypeOptions.BOOL:
      modelCode += `this.${key} !== undefined ? (ret.${key} = this.${key}) : null;`;
      break;
    case valueTypeOptions.CLASS:
      modelCode += `this.${key} && (ret.${key} = this.${key}.toServer());`;
      break
  }
  // console.log('toServer:', modelCode)
  return modelCode;
}

function parse(key, type) {
  let modelCode = '';
  switch (type) {
    case valueTypeOptions.STRING:
      modelCode += `model.${key} = data.${key} || ${type};`;
      break;
    case valueTypeOptions.ARRAY:
      modelCode += `model.${key} = _.map(data.${key}, Class.parse) || [];`;
      break;
    case valueTypeOptions.OBJ:
      modelCode += `model.${key} = _.isEmpty(data.${key}) ? null : data.${key};`;
      break;
    case valueTypeOptions.KEYCLASSOBJ:
      modelCode += `model.${key} = {};\n`
                 + `_.each(data.${key}, (clazz, key) => {\n`
                 + `  model.${key}[key] = Class.parse(clazz);\n`
                 + `})`;
      break;
    case valueTypeOptions.CLASSARRAY:
      modelCode += `model.${key} = _.map(data.${key}, Class.parse) || [];`;
      break;
    case valueTypeOptions.BOOL:
      modelCode += `model.${key} = data.${key} !== undefined ? data.${key} : undefined;`;
      break;
    case valueTypeOptions.CLASS:
      modelCode += `model.${key} = Class.parse(data.${key});`;
      break
  }
  // console.log('parse:', modelCode)
  return modelCode;
}

  return {
    valueTypes: valueTypeOptions,
    prop,
    construct,
    toServer,
    parse
  }

}))
